//
//  MSRichLabel.m
//  Community
//
//  Created by luo danal on 3/1/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "MSRichLabel.h"
#import "MSTextImage.h"
#import "MSUIImage+Additiions.h"

#define kLabelLineHeight12 18.f
#define kLabelLineHeight14 20.f

#define kRLLabelLineMargin 4.f
#define kDescrMaxLines 2

#define kRLFaceLeftDelimiter @"["
#define kRLFaceRightDelimiter @"]"
#define kRLFaceFileNameLength 3
#define KRLDefaultLineHeight 18.f
#define kRLFaceFrameWidth KRLDefaultLineHeight
#define kRLDefaultFontSize 14.f
#define kCommFacesMargin 2.f

//#3C71D6  蓝
//#EC4C36 红
#define kBuleColor [UIColor colorWithRed:60/255.0 green:113/255.0 blue:214/255.f alpha:1.0]
#define kRedColor [UIColor colorWithRed:236/255.0 green:76/255.0 blue:54/255.f alpha:1.0]

#define kRLTagTop 2001
#define kRLTagGold 2002
#define kRLTagImage 2003

@interface MSRichLabel ()
@property (strong, nonatomic) NSMutableAttributedString *coreText;
@end

@implementation MSRichLabel
@synthesize coreText;

+ (CGSize)sizeConstrainedToSize:(CGSize)size attributedString:(NSAttributedString *)string font:(UIFont *)font breakMode:(int)breakMode{
    CGSize realSize = size;
    CTFramesetterRef framesetter =  CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
    CFRange strRange = CFRangeMake(0, [string length]);
    CFDictionaryRef frameAttributes = NULL;
    CFRange fitRange;
    realSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, strRange, frameAttributes, size, &fitRange);
    CFRelease(framesetter);
    return realSize;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor lightGrayColor];
        CATextLayer *lyr = [CATextLayer layer];
        lyr.contentsScale = [UIScreen mainScreen].scale;
        lyr.frame = self.bounds;
        lyr.wrapped = YES;
        [self.layer addSublayer:lyr];
        _textLayer = lyr;
    }
    return self;
}

- (CGSize)sizeConstrainedToSize:(CGSize)size{
    //    如果想要计算NSAttributedString所要的size，就需要用到这个API：
    //
    //    CTFramesetterSuggestFrameSizeWithConstraints，用NSString的sizeWithFont算多行时会算不准的，因为在CoreText里，行间距也是你来控制的。
    
    [self configAttributes];
    
    CGSize realSize = size;
    CTFramesetterRef framesetter =  CTFramesetterCreateWithAttributedString((CFAttributedStringRef)coreText);
    CFRange strRange = CFRangeMake(0, [coreText length]);
    CFDictionaryRef frameAttributes = NULL;
    CFRange fitRange;
    realSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, strRange, frameAttributes, size, &fitRange);
    CFRelease(framesetter);
    return realSize;
}

- (void)setText:(NSString *)text{
    self.coreText = [[NSMutableAttributedString alloc] initWithString:text];
}

- (NSString *)text{
    return self.coreText.string;
}

- (void)setHTMLText:(NSString *)htmlText{
    //Parse
    
}

#pragma mark - Style

- (void)setFont:(UIFont *)font inRange:(NSRange)range{
    [coreText addAttribute:(NSString *)kCTFontAttributeName
                     value:(MSBridge id)CTFontCreateWithName((MSBridge CFStringRef)font.fontName, font.pointSize, NULL) range:range];
}

- (void)setColor:(UIColor *)color inRange:(NSRange)range{
    [coreText addAttribute:(NSString *)kCTForegroundColorAttributeName
                     value:(MSBridge id)color.CGColor
                     range:range];
}

- (void)setUnderline:(UIColor *)color inRange:(NSRange)range{
    [coreText addAttribute:(NSString *)kCTUnderlineColorAttributeName
                     value:(id)color.CGColor
                     range:range];
    [coreText addAttribute:(NSString *)kCTUnderlineStyleAttributeName
                     value:(id)[NSNumber numberWithInt:kCTUnderlineStyleSingle]
                     range:range];
}

- (void)setStrokeWidth:(CGFloat)width inRange:(NSRange)range{
    [coreText addAttribute:(NSString *)kCTStrokeWidthAttributeName
                     value:(id)[NSNumber numberWithFloat:width]
                     range:range];
}

- (void)configAttributes{
    int strLen = coreText.length;
    {
        //Config font
        [coreText addAttribute:(NSString *)kCTFontAttributeName
                         value:(MSBridge id)CTFontCreateWithName((MSBridge CFStringRef)self.font.fontName,
                                                                 self.font.pointSize,
                                                                 NULL)
                         range:NSMakeRange(0, strLen)];
        
        //Config text color
        [coreText addAttribute:(NSString *)kCTForegroundColorAttributeName
                         value:(id)self.textColor.CGColor
                         range:NSMakeRange(0, strLen)];
        
        //Config paragraph & line space
        CTParagraphStyleSetting lineBreakMode;
        CTLineBreakMode lineBreak = kCTLineBreakByWordWrapping; //换行模式
        lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;
        lineBreakMode.value = &lineBreak;
        lineBreakMode.valueSize = sizeof(CTLineBreakMode);
        //行间距
        CTParagraphStyleSetting LineSpacing;
        CGFloat spacing = -2.0;  //指定间距
        LineSpacing.spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;
        LineSpacing.value = &spacing;
        LineSpacing.valueSize = sizeof(CGFloat);
        
        CTParagraphStyleSetting settings[] = {lineBreakMode,LineSpacing};
        CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, 2);   //第二个参数为settings的长度
        [coreText addAttribute:(NSString *)kCTParagraphStyleAttributeName
                         value:(MSBridge id)paragraphStyle
                         range:NSMakeRange(0, strLen)];
    }
    
}

#define DISPLAY_IN_TEXTLAYER 0

#if DISPLAY_IN_TEXTLAYER

- (void)layoutSubviews{
    _textLayer.string = coreText;
    [_textLayer setNeedsDisplay];
}

#else

- (void)drawRect:(CGRect)rect
{
    [self configAttributes];
    
    //    CTFramesetter是CTFrame的创建工厂，NSAttributedString需要通过CTFrame绘制到界面上，得到CTFramesetter后，创建path（绘制路径），然后得到CTFrame，最后通过CTFrameDraw方法绘制到界面上。
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextConcatCTM(ctx, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, rect.size.height), 1.f, -1.f));
    
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((MSBridge CFAttributedStringRef)coreText);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, rect);
    
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
    CFRelease(path);
    CFRelease(framesetter);
    
    CTFrameDraw(frame, ctx);
    CFRelease(frame);
}

#endif

@end

/*
@implementation MSRichLabel
@synthesize richText = _richText;
@synthesize isTop;
@synthesize isGold;
@synthesize hasImage;
@synthesize maxLines;
@synthesize trancated;
@synthesize enableSelection = _enableSelection;

- (void)dealloc {
    [_richText release];
    [super dealloc];
}
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.maxLines = kDescrMaxLines;
//        self.backgroundColor = [UIColor grayColor];
    }
    return self;
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(ctx, self.textColor.CGColor);
    UIFont *ft = self.font;
    NSInteger count = [self.text length];
    NSString *c;
    CGSize size = CGSizeMake(100.f, 20.f);
    CGSize iSize;
    CGPoint loc = CGPointZero;
    CGFloat lineH = ft.lineHeight; //ft.pointSize;  //kTBDescriptionLineHeight
    CGFloat maxY =  self.maxLines * (kRLLabelLineMargin + lineH);     //kTBDescriptionLineHeight//kDescrMaxLines*kLabelLineHeight12;
    CGFloat maxX = rect.size.width;
//    [[self viewWithTag:kRLTagTop] removeFromSuperview];
//    [[self viewWithTag:kRLTagGold] removeFromSuperview];
//    [[self viewWithTag:kRLTagImage] removeFromSuperview];
// 
   //remove subviews for reusing
    for (UIView *v in self.subviews) {
        if ([v isKindOfClass:[MSTextImage class]]){
            [v removeFromSuperview];
        }
    }
    //---test---
    if (self.isTop) {
        CGRect frm = CGRectMake(loc.x, loc.y, 30.f, kLabelLineHeight12);
        MSTextImage *ti = [MSTextImage imageWithFrame:frm title:@"置顶" titleColor:nil bgColor:kBuleColor withCorners:YES];
        ti.tag = kRLTagTop;
        [self addSubview:ti];
        loc.x += frm.size.width;
        loc.x += kCommFacesMargin;
    }
    
    if (self.isGold) {
        CGRect frm = CGRectMake(loc.x, loc.y, 18.f, kLabelLineHeight12);
        frm.origin.x = loc.x;
        MSTextImage *ti2 = [MSTextImage imageWithFrame:frm title:@"精" titleColor:nil bgColor:kRedColor withCorners:YES];
        ti2.tag = kRLTagGold;
        [self addSubview:ti2];
        loc.x += frm.size.width;
        loc.x += kCommFacesMargin;
    }
    if (self.hasImage) {
        
        UIImage *img1 = [UIImage imageNamed:@"pic"];
        UIImage *img2 = [img1 resizeToSize:CGSizeMake(22.f, 16.f)];
        CGRect frm = CGRectMake(loc.x, loc.y, img2.size.width, img2.size.height);
        MSTextImage *ti3 = [MSTextImage imageWithFrame:frm image:img2 withCorners:NO];
        ti3.tag = kRLTagImage;
        //        [img2 drawAtPoint:loc];
        [self addSubview:ti3];
        loc.x += img2.size.width;
        loc.x += kCommFacesMargin;
    }
 
    //---test end----
    
    NSString *faceFile = nil;
    NSString *faceFilePath = nil;
    UIImage *face = nil;
    CGRect faceFrame;
    CGFloat fw = kRLFaceFrameWidth;
    NSFileManager *fm = [NSFileManager defaultManager];
    for (int i = 0; i < count; i++) {
        c = [self.text substringWithRange:NSMakeRange(i, 1)];

        if ([c isEqualToString:kRLFaceLeftDelimiter]) {
            faceFile = [self.text substringWithRange:NSMakeRange(i + 1, kRLFaceFileNameLength)];
            faceFilePath = [[NSBundle mainBundle] pathForResource:faceFile ofType:@"png"];
            if ([fm fileExistsAtPath:faceFilePath]) {
                
                face = [UIImage imageWithContentsOfFile:faceFilePath];
                faceFrame = CGRectMake(loc.x, loc.y, fw, fw);
                MSTextImage *ti = [MSTextImage imageWithFrame:faceFrame image:face withCorners:NO];
                [self addSubview:ti];
                i += kRLFaceFileNameLength + 1;
                loc.x += fw;
                continue;
            }
        }
        
        iSize = [c sizeWithFont:ft constrainedToSize:size lineBreakMode:UILineBreakModeWordWrap];
        
        if (loc.x + iSize.width > maxX) {  //outside
            loc.x = 0;
            loc.y += lineH + kRLLabelLineMargin;
        }
//        if (loc.y >= maxY) {
        
        if (loc.y + lineH + kRLLabelLineMargin >= maxY && loc.x + 2*iSize.width > maxX) {
            if (self.trancated) {
                //Replace the last word with ...
                [@"..." drawAtPoint:loc withFont:ft];
                break;
            }
        }else {
            if (_selectAll) {
                CGContextSaveGState(ctx);
                CGContextAddRect(ctx, CGRectMake(loc.x, loc.y, iSize.width, lineH + kRLLabelLineMargin));
                CGContextSetFillColorWithColor(ctx, [UIColor colorWithRed:204.f/255.f green:221.f/255.f blue:237.f/255.f alpha:1.f].CGColor);
                CGContextFillPath(ctx);
                CGContextRestoreGState(ctx);
            }
            
            [c drawAtPoint:loc withFont:ft];
        }
        loc.x += iSize.width;
        
    }
    
}


- (void)setRichText:(NSString *)richText{
    if (_richText != richText) {
        [_richText release];
        _richText = [richText copy];
    }
}


- (void)setEnableSelection:(BOOL)enableSelection{
    if (!_enableSelection && enableSelection) {
        UILongPressGestureRecognizer *lp = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];
        [self addGestureRecognizer:lp];
        [lp release];
        self.userInteractionEnabled = YES;
    }
    _enableSelection = enableSelection;
}

- (void)longPressAction:(UILongPressGestureRecognizer *)g{
    [self becomeFirstResponder];
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setTargetRect:CGRectMake(0, 0, 1, 1) inView:self];
    [menu setMenuVisible:YES animated:YES];
    _selectAll = YES;
    [self setNeedsDisplay];
}

- (BOOL)canBecomeFirstResponder{
    return self.enableSelection;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
    if (action == @selector(copy:)) {
        return YES;
    }
    return NO;
}

- (void)copy:(id)sender{
    _selectAll = NO;
    [self setNeedsDisplay];
    UIPasteboard *board = [UIPasteboard generalPasteboard];
    [board setValue:self.text forPasteboardType:@"public.utf8-plain-text"];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    if (_selectAll) {
        _selectAll = NO;
        [self setNeedsDisplay];
    }
}

#pragma mark - Class methods
+ (CGFloat)defaultLineHeight{
    return KRLDefaultLineHeight + kRLLabelLineMargin;
}

+ (NSInteger)rowsOfText:(NSString *)text withFont:(UIFont *)font forWidth:(CGFloat)width{
    if (font == nil) {
        font = [UIFont systemFontOfSize:kRLDefaultFontSize];
    }
    NSInteger lines = 1;
    NSInteger count = [text length];
    NSString *c = nil;
    CGSize size = CGSizeMake(100.f, 20.f);
    CGSize iSize;
    CGPoint loc = CGPointZero;
    CGFloat maxX = width;
    NSString *faceFile = nil;
    NSString *faceFilePath = nil;
//    UIImage *face = nil;
    CGRect faceFrame;
    CGFloat fw = kRLFaceFrameWidth;
    NSFileManager *fm = [NSFileManager defaultManager];
    for (int i = 0; i < count; i++) {
        c = [text substringWithRange:NSMakeRange(i, 1)];
        
        if ([c isEqualToString:kRLFaceLeftDelimiter]) {
            faceFile = [text substringWithRange:NSMakeRange(i + 1, kRLFaceFileNameLength)];
            faceFilePath = [[NSBundle mainBundle] pathForResource:faceFile ofType:@"png"];
            if ([fm fileExistsAtPath:faceFilePath]) {
                
                faceFrame = CGRectMake(loc.x, loc.y, fw, fw);
                i += kRLFaceFileNameLength + 1;
                loc.x += fw;
                continue;
            }
        }
        
        iSize = [c sizeWithFont:font constrainedToSize:size lineBreakMode:UILineBreakModeWordWrap];
        
        if (loc.x + iSize.width > maxX) {  //outside
            lines++;
            loc.x = 0;
            loc.y += font.lineHeight + kRLLabelLineMargin;  //kTBDescriptionLineHeight + kRLLabelLineMargin;        //margin
        }
        loc.x += iSize.width;
        
    }
    return lines;
}

+ (CGSize)sizeOfText:(NSString *)text withFont:(UIFont *)font forWidth:(CGFloat)width{
    if (font == nil) {
        font = [UIFont systemFontOfSize:kRLDefaultFontSize];
    }
    NSInteger lines = 1;
    NSInteger count = [text length];
    NSString *c = nil;
    CGSize size = CGSizeMake(100.f, 20.f);
    CGSize iSize;
    CGPoint loc = CGPointZero;
    CGFloat maxX = width;
    NSString *faceFile = nil;
    NSString *faceFilePath = nil;
    //    UIImage *face = nil;
    CGRect faceFrame;
    CGFloat fw = kRLFaceFrameWidth;
    NSFileManager *fm = [NSFileManager defaultManager];
    for (int i = 0; i < count; i++) {
        c = [text substringWithRange:NSMakeRange(i, 1)];
        
        if ([c isEqualToString:kRLFaceLeftDelimiter]) {
            faceFile = [text substringWithRange:NSMakeRange(i + 1, kRLFaceFileNameLength)];
            faceFilePath = [[NSBundle mainBundle] pathForResource:faceFile ofType:@"png"];
            if ([fm fileExistsAtPath:faceFilePath]) {
                
                faceFrame = CGRectMake(loc.x, loc.y, fw, fw);
                i += kRLFaceFileNameLength + 1;
                loc.x += fw;
                continue;
            }
        }
        
        iSize = [c sizeWithFont:font constrainedToSize:size lineBreakMode:UILineBreakModeWordWrap];
        
        if (loc.x + iSize.width > maxX) {  //outside
            lines++;
            loc.x = 0;
            loc.y += font.lineHeight + kRLLabelLineMargin;  //kTBDescriptionLineHeight + kRLLabelLineMargin;        //margin
        }
        loc.x += iSize.width;
        
    }
    return CGSizeMake(width, loc.y + font.lineHeight);
}

@end
*/